/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bsk;

import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import komunikaty.Card;

/**
 *
 * @author Lukasz
 */
public class SVoting {
    //generate the RSA key pair

    public synchronized static KeyPair generateRSAKeyPair() throws Exception {
        KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
        kpGen.initialize(1024, new SecureRandom());
        return kpGen.genKeyPair();
    }

    //pobranie publicznego wykĹ‚adnika
    public synchronized static BigInteger getPublicExponent(KeyPair keypair) {
        RSAPublicKey pubKey = (RSAPublicKey) keypair.getPublic();
        return pubKey.getPublicExponent();
    }

    //pobranie prywatnego wykĹ‚adnika
    public synchronized static BigInteger getPrivateExponent(KeyPair keypair) {
        RSAPrivateKey privKey = (RSAPrivateKey) keypair.getPrivate();
        return privKey.getPrivateExponent();
    }

    //pobranie liczby modulo
    public synchronized static BigInteger getModul(KeyPair keypair) {
        RSAPublicKey pubKey = (RSAPublicKey) keypair.getPublic();
        return pubKey.getModulus();
    }

    //odciemianie wiadomoĹ›ci: m = m'r^{-e} mod(n)
    public synchronized static BigInteger odciemniaj(BigInteger messageZaciemniona, BigInteger R, BigInteger wykPublic, BigInteger modul) {
        return messageZaciemniona.multiply(R.modInverse(modul).modPow(wykPublic, modul)).mod(modul);
    }
    
    //podpisanie wiadomoĹ›ci zaciemnionej: s'=(m')^d mod(n)
    public synchronized static BigInteger podpiszZaciemnione(BigInteger messageZaciemniona, BigInteger wykPrivate, BigInteger modul) {
        return messageZaciemniona.modPow(wykPrivate, modul);
    }

    //odkodowanie wiadomoĹ›ci: h=f^D2 mod(N2), z=h^E1 mod(N1)
    public synchronized static BigInteger odkodowanieWiadom(BigInteger podpisanaWiad, BigInteger wykPublic, BigInteger modul, BigInteger wykPrivate2, BigInteger modul2) {
        BigInteger h = podpisanaWiad.modPow(wykPrivate2, modul2);
        return h.modPow(wykPublic, modul);
    }
    
    //odciemianie jednej karty
    public synchronized static void odciemniajKarte(Card karta, BigInteger R, BigInteger wykPublic, BigInteger modul) {
        for (int i = 0; i < karta.votes.length; i++) {
            karta.votes[i].candidate = odciemniaj(karta.votes[i].candidate, R, wykPublic, modul);
            karta.votes[i].serial = odciemniaj(karta.votes[i].serial, R, wykPublic, modul);
        }
    }
    
    //odciemianie tablicy kart
    public synchronized static void odciemniajKarty(Card[] karty, BigInteger[] R, BigInteger wykPublic, BigInteger modul) {
        for (int i = 0; i < karty.length; i++) {
            odciemniajKarte(karty[i], R[i], wykPublic, modul);
        }
    }
    
    //podpisanie karty zaciemnionej
    public synchronized static void podpiszZaciKarte(Card karta, BigInteger wykPrivate, BigInteger modul) {
        for (int i = 0; i < karta.votes.length; i++) {
            karta.votes[i].candidate = podpiszZaciemnione(karta.votes[i].candidate, wykPrivate, modul);
            karta.votes[i].serial = podpiszZaciemnione(karta.votes[i].serial, wykPrivate, modul);
        }
    }
    
    //okodowanie gĹ‚osu
    public synchronized static void odkodowanieGlosu(Card.Vote glos, BigInteger wykPublic, BigInteger modul, BigInteger wykPrivate2, BigInteger modul2) {
        glos.candidate = odkodowanieWiadom(glos.candidate, wykPublic, modul, wykPrivate2, modul2);
        glos.serial = odkodowanieWiadom(glos.serial, wykPublic, modul, wykPrivate2, modul2);
    }
}
